package com.leyou.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.leyou.common.constants.MQConstants;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exceptions.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.vo.PageResultVO;
import com.leyou.item.dto.*;
import com.leyou.item.entity.Sku;
import com.leyou.item.entity.Spu;
import com.leyou.item.entity.SpuDetail;
import com.leyou.mapper.SkuMapper;
import com.leyou.mapper.SpuDetailMapper;
import com.leyou.mapper.SpuMapper;
import com.leyou.service.GoodsService;
import com.leyou.service.IBrandService;
import com.leyou.service.ICategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author xiuer
 * @description 商品业务层
 * @create 2019/6/27 21:38
 */
@Service
@Slf4j
public class GoodsServiceImpl implements GoodsService {
    @Autowired
    private SpuMapper spuMapper;

    @Autowired
    private SkuMapper skuMapper;
    @Autowired
    private SpuDetailMapper spuDetailMapper;

    @Autowired
    private ICategoryService categoryService;

    @Autowired
    private IBrandService brandService;
    @Autowired
    private AmqpTemplate amqpTemplate;


    /**
     * 商品分页查询
     */
    @Override
    public PageResultVO<SpuDTO> goodsQueryPage(String key, Boolean saleable, Integer page, Integer rows) {
        //分页
        PageHelper.startPage(page, rows);

        List<Spu> list = spuMapper.queryPageSpu(key, saleable);
        if (CollectionUtils.isEmpty(list)) {
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        PageInfo<Spu> pageInfo = new PageInfo<>(list);
        List<SpuDTO> spuDTOS = BeanHelper.copyWithCollection(list, SpuDTO.class);
        queryCategoryNameAndBrandName(spuDTOS);
        return new PageResultVO<>(pageInfo.getTotal(), spuDTOS, pageInfo.getPages());
    }

    /**
     * 查询商品分类信息和品牌信息
     */
    private void queryCategoryNameAndBrandName(List<SpuDTO> spuDTOS) {
        //查询分类
        for (SpuDTO spuDTO : spuDTOS) {
            String categoryName = categoryService.queryCategoryByCids(spuDTO.getCategoryIds()).stream()
                    .map(CategoryDTO::getName)
                    .collect(Collectors.joining("/"));
            spuDTO.setCategoryName(categoryName);
            //查询品牌
            BrandDTO brandDTO = brandService.queryBrandByBid(spuDTO.getBrandId());
            spuDTO.setBrandName(brandDTO.getName());
        }


    }


    /**
     * 新增商品 （sku spu spu_detail）
     *
     * @param spuDTO
     * @return
     */
    @Override
    @Transactional
    public void insertGoods(SpuDTO spuDTO) {
        //新增spu表数据 从spuDTO中取出pu数据 // 如果默认下架 用spuDTO.setSaleable(false)方法来设置
        Spu spu = BeanHelper.copyProperties(spuDTO, Spu.class);
        int affectRows = spuMapper.insertGoodBySpu(spu);
        if (affectRows != 1) {
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }

        //新增spudetail表 注意从spu中获取id（主键回显）
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
        spuDetailDTO.setSpuId(spu.getId());
        affectRows = spuDetailMapper.insertGoodsBySpuDetail(BeanHelper.copyProperties(spuDetailDTO, SpuDetail.class));
        if (affectRows != 1) {
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }
        //新增sku表 注意从spu中获取id（主键回显）
        List<SkuDTO> skuDTOList = spuDTO.getSkus();
        for (SkuDTO skuDTO : skuDTOList) {
            skuDTO.setSpuId(spu.getId());
        }
        List<Sku> skuList = BeanHelper.copyWithCollection(skuDTOList, Sku.class);
        affectRows = skuMapper.insertGoodsBySku(skuList);
        if (affectRows != skuList.size()) {
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }
    }

    /**
     * 更新商品
     *
     * @param spuDTO
     */
    @Override
    @Transactional
    public void updateGoods(SpuDTO spuDTO) {

        Long spuId = spuDTO.getId();
        if (spuId == null) {
            // 请求参数有误
            throw new LyException(ExceptionEnum.INVALID_PARAM_ERROR);
        }
        //更新 sku表
        // 1. 先删除关联的spu_id 所有记录， 删除Sku表
        int affectRows = skuMapper.deleteSkuBySpuId(spuId);
        //先查询以前数量
        int size = skuMapper.selectCountBySkuSpuId(spuId);
        if (size > 0) {
            if (affectRows != size) {
                throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
            }
        }
        //更新 spu表  注意spu的上下架属性不用更新
        Spu spu = BeanHelper.copyProperties(spuDTO, Spu.class);

        affectRows = spuMapper.updateSpuByid(spu);
        if (affectRows != 1) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
        //更新 spuDetail表
        affectRows = spuDetailMapper.updateSpuDetailBySpuId(BeanHelper.copyProperties(spuDTO.getSpuDetail(), SpuDetail.class));
        if (affectRows != 1) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }

        //2.新增sku表数据  注意从spu中获取id（主键回显）
        List<SkuDTO> skuDTOList = spuDTO.getSkus();
        for (SkuDTO skuDTO : skuDTOList) {
            skuDTO.setSpuId(spu.getId());
            skuDTO.setEnable(false);
        }
        List<Sku> skuList = BeanHelper.copyWithCollection(skuDTOList, Sku.class);
        affectRows = skuMapper.insertGoodsBySku(skuList);
        if (affectRows != skuList.size()) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
    }

    /**
     * 上下架商品
     *
     * @Param id Sku主键
     * @Param saleable 上下架状态
     */
    @Override
    @Transactional
    public void updateSaleableBySkuId(Long id, Boolean saleable) {
        //更改spu表  saleable 字段
        int affectRows = spuMapper.updateSaleableBySpuId(id, saleable);
        if (affectRows != 1) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
        //更改 sku表 enable
        affectRows = skuMapper.updateBySkuSpuId(id, saleable);
        //健壮性判断 聚合查询符合条件spuid的条数与更新影响行数是否相等
        int selectRows = skuMapper.selectCountBySkuSpuId(id);
        if (affectRows != selectRows) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
        //上下架商品发送MQ
        //定义发送商品的Rotingkey 上架 up 下架 down
        String itemKey = saleable ? MQConstants.RoutingKey.ITEM_UP_KEY : MQConstants.RoutingKey.ITEM_DOWN_KEY;
        log.info("商品微服务上下架状态", itemKey);
        amqpTemplate.convertAndSend(MQConstants.Exchange.ITEM_EXCHANGE_NAME, itemKey, id);

    }

    /**
     * 数据回显 根据 spu_id查询 spuetail
     *
     * @param id
     * @return
     */
    @Override
    public SpuDetailDTO selectSpuDetail(Long id) {
        SpuDetail spuDetail = spuDetailMapper.selectSpuDetailBySpuId(id);
        if (spuDetail == null) {
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        return BeanHelper.copyProperties(spuDetail, SpuDetailDTO.class);
    }


    /**
     * 数据回显 根据 spu_id查询 sku
     */
    @Override
    public List<SkuDTO> selectSku(Long id) {
        List<Sku> list = skuMapper.selectSkuBySpuId(id);
        if (CollectionUtils.isEmpty(list)) {
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        return BeanHelper.copyWithCollection(list, SkuDTO.class);
    }

    /**
     * 根据spuId查询spu
     */
    @Override
    public SpuDTO querySpuById(Long id) {
        Spu spu = spuMapper.querySpuById(id);
        if (spu == null) {
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        SpuDTO spuDTO = BeanHelper.copyProperties(spu, SpuDTO.class);
        spuDTO.setSpuDetail(selectSpuDetail(id));
        return spuDTO;
    }

    /**
     * 根据sku ids 查询sku
     *
     * @param ids
     * @return
     */
    @Override
    public List<SkuDTO> querySkuByIds(List<Long> ids) {
        List<Sku> list = skuMapper.querySkuByIds(ids);
        if (CollectionUtils.isEmpty(list)) {
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        return BeanHelper.copyWithCollection(list, SkuDTO.class);
    }

    /**
     * 根据订单id和商品的数量减库存
     */
    @Override
    public void minusStock(Map<Long, Integer> numCartMap) {
        for (Long skuId : numCartMap.keySet()) {
            try {
                Long affectRows = skuMapper.minusStock(skuId, numCartMap.get(skuId));
                if (affectRows != 1) {
                    throw new RuntimeException("库存不足");
                }
            } catch (Exception e) {
                log.error("【商品微服务】库存异常 原因{}", e.getMessage(), e);
                throw new LyException(ExceptionEnum.STOCK_NOT_ENOUGH);
            }
        }
    }
}
